<?php

abstract class Restful {

    /**
     * 追踪器对象
     *
     * @var object
     */
    protected $trace;

    /**
     * 安全检测对象
     *
     * @var object
     */
    protected $safety;

    /**
     * session处理对象
     *
     * @var object
     */
    protected $session;

    /**
     * 参数处理对象
     *
     * @var object
     */
    protected $param;

    /**
     * 初始化
     */
    public function __construct() {
        // 初始化对象
        $this->trace = new Trace();
        $this->safety = new Safety();
        $this->session = new Session();
        $this->param = new Param();

        // 开始工作
        $this->_working();
    }

    /**
     * 抽象方法，子类必须继承。处理逻辑的主要位置
     *
     * @return array
     */
    abstract public function action();

    /**
     * 参数验证专用方法，子类可以覆盖
     *
     * @return array
     */
    public function valid() {
        return [];
    }

    /**
     * 结束脚本执行，并输出结果给用户
     *
     * @param array $res 脚本执行结果
     * @return void
     */
    protected function end($res) {
        $this->trace->end($res);
        echo json_encode($res);
        exit;
    }

    /**
     * Restful工作方法
     *
     * @return void
     */
    private function _working() {

        // 初始化追踪器
        $this->trace->init();

        // 验证非法IP
        $section = $this->safety->validIP();
        if (!$section['success']) {
            $this->end(Res::eIllegal($section['msg']));
        }

        // 初始化Session
        $section = $this->session->init();
        if (!$section['success']) {
            $this->end(Res::eDanger($section['msg']));
        }

        // 验证非法用户ID
        $section = $this->safety->validUserID();
        if (!$section['success']) {
            $this->end(Res::eDanger($section['msg']));
        }

        // 过滤非法参数
        $this->param->filter();

        // 细致验证所有参数是否合法
        $section = $this->param->valid($this->valid());
        if (!$section['success']) {
            $this->end(Res::eParam($section['msg']));
        }

        // 调用action，取回执行结果
        $result = $this->action();

        // 将结果送到end，结束脚本执行
        $this->end($result);
    }
}
